﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarbonExchange.AmeeQuery;
using CarbonExchange.Dal;

namespace CarbonExchange.Bll
{
    public class AnswerFactory : FactoryBase<Answer>
    {

        public AnswerFactory() : base() { }

        public AnswerFactory(IAmeeCommand ameeCommand) : base(ameeCommand) { }

        public AnswerFactory(Context dalContext) : base(dalContext) { }

        public AnswerFactory(IAmeeCommand ameeCommand, Context dalContext) : base(ameeCommand, dalContext) { }

        protected override void MarkItemForDeletion(Answer item)
        {
            var tmp = item.Convert(DalContext);
            if (tmp != null)
            {
                tmp.Deleted = true;
            }
        }

        protected override void Validate(IQueryable<Answer> items, CarbonExchange.Bll.Exceptions.ValidationException exp)
        {
            items.Validate(exp, DalContext);
        }

        protected override void PopulateDataChanges(Answer item, object dataItem)
        {
            var tmpDataItem = dataItem as Dal.Answer;
            if (tmpDataItem != null)
            {
                item.Id = tmpDataItem.Id;
                item.CID = tmpDataItem.CID;
                if (item.AnswerItems != null)
                {
                    foreach (var tmpAnswerItem in tmpDataItem.AnswerItems)
                    {
                        var answerItem = item.AnswerItems.Where(x => x.Name == tmpAnswerItem.Name).SingleOrDefault();
                        if (answerItem == null)
                        {
                            item.AnswerItems.Add(tmpDataItem.Convert(DalContext));
                        }
                        else
                        {
                            answerItem.Id = tmpAnswerItem.Id;
                            answerItem.CID = tmpAnswerItem.CID;
                            answerItem.AnswerId = item.Id;
                        }
                    }
                }
            }
        }

        protected override object GetDataItemForUpdate(Answer item)
        {
            return item.Convert(DalContext);
        }

        private IQueryable<Dal.Answer> GetSelection()
        {
            return DalContext.Answers.Where(x => !x.Deleted);
        }

        public Answer GetByAuditIdAndQuestionId(int auditId, int questionId)
        {
            return GetSelection().Where(x => x.AuditId == auditId && x.QuestionId == questionId).SingleOrDefault().Convert(DalContext);
        }

        public IQueryable<Answer> GetAllByAuditIdAndSectionId(int auditId, int sectionId)
        {
            return GetSelection().Where(x => x.AuditId == auditId && x.Question.SectionId == sectionId).Convert(DalContext);
        }
    }

    public static class AnswerConverter
    {
        internal static Answer Convert(this Dal.Answer source, Dal.Context context)
        {
            return ConvertItem(source, context);
        }

        internal static IQueryable<Answer> Convert(this IQueryable<Dal.Answer> source, Dal.Context context)
        {
            return source.Select(x => ConvertItem(x, context));
        }

        private static Answer ConvertItem(Dal.Answer item, Dal.Context context)
        {
            if (item != null)
            {
                return new Answer()
                {
                    AuditId = item.AuditId,
                    CID = item.CID,
                    Id = item.Id,
                    Settings = item.Settings == null ? new Newtonsoft.Json.Linq.JObject() : Newtonsoft.Json.Linq.JObject.Parse(item.Settings),
                    QuestionId = item.QuestionId,
                    AnswerItems = new CarbonExchange.LinqUtilities.LazyList<AnswerItem>(context.AnswerItems.Where(x=> x.AnswerId == item.Id).Select(x => new AnswerItemFactory.JoinHelper(x, x.Answer.Question, x.Answer.Audit.AuditKey, x.Answer.Question.SectionId)).Convert())
                };
            }
            else
            {
                return null;
            }
        }

        internal static Dal.Answer Convert(this Answer source, Dal.Context context)
        {
            return ConvertItem(source, context);
        }

        internal static IQueryable<Dal.Answer> Convert(this IQueryable<Answer> source, Dal.Context context)
        {
            return source.Select(x => ConvertItem(x, context));
        }

        private static Dal.Answer ConvertItem(Answer item, Dal.Context context)
        {
            if (item != null)
            {
                Dal.Answer tmp = null;
                if (item.Id == 0)
                {
                    tmp = new CarbonExchange.Dal.Answer();
                    context.Answers.InsertOnSubmit(tmp);
                }
                else
                {
                    tmp = context.Answers.Where(x => !x.Deleted && x.Id == item.Id).Single();
                }
                tmp.AuditId = item.AuditId;
                if (item.Settings != null)
                {
                    var tmpStringBuider = new StringBuilder();
                    var tmpStringWriter = new System.IO.StringWriter(tmpStringBuider);
                    var tmpJsonWriter = new Newtonsoft.Json.JsonTextWriter(tmpStringWriter);
                    item.Settings.WriteTo(tmpJsonWriter);
                    tmp.Settings = tmpStringBuider.ToString();
                }
                else
                {
                    tmp.Settings = null;
                }
                tmp.QuestionId = item.QuestionId;
                if(item.AnswerItems != null)
                {
                    tmp.AnswerItems.Assign(item.AnswerItems.AsQueryable().Convert(context));
                }
                return tmp;
            }
            else
            {
                return null;
            }
        }

        internal static void Validate(this IQueryable<Answer> source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
            foreach (var item in source)
                item.Validate(e, context);
        }

        internal static void Validate(this Answer source, CarbonExchange.Bll.Exceptions.ValidationException e, Dal.Context context)
        {
        }
    }
}
